﻿//Copyright 2011 University of Southampton 
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.Diagnostics;
using SharePointEntityProject.EntityEditorLib;
using SharePointEntityProject.Properties;
using Exceptions;
using SharePointEntityProjectLibrary;
using UniversityOfSouthampton.Taxonomy;
using Microsoft.SharePoint.Utilities;


namespace EntityEditorLib
{

 

    internal class EntityEditor
    {

        string ListName;
        string SiteUrl;// = Resources.DefaultSharepoint2010SiteURL;
    

        //The tax group for all the metadata in this list
        TaxonomyCreateGroupResult MetadataGroupInfo;
        

        internal EntityEditor(string SiteUrl, string ListName)
        {
            this.SiteUrl = SiteUrl;
            this.ListName = ListName;
            //Check this is running in a sandbox!
            if (!System.AppDomain.CurrentDomain.FriendlyName.Contains("Sandbox"))
            {
                throw new Exception("Not sandboxed");
            }

        }

        public SPList CreateEntityStorageList(string listName, string description){
             
            Debug.WriteLine(String.Format("Create storage list : {0} - {1}", listName, description));

            //Get a list manager
            using (ListManagementLib listManager = new ListManagementLib(SiteUrl))
            {

                //Get the list settings
                
                    ListSettings listSettings = listManager.GetListSettings(listName); //Handy if it exists
               
                
                //Set the properties that are required for an Entity storage list
                if (listName != null)
                {
                    listSettings.title = listName;
                }
                else
                {
                    //Special , these are webpart properties, user set
                    throw new InvalidWebpartValue("Invalid List name web part parameter (Configure web part)");
                }

                if(description != null){
                listSettings.description = description;
                }
                else
                {
                    //Special , these are webpart properties, user set
                    throw new InvalidWebpartValue("Invalid List name web part parameter (Configure web part)");
                }

                if (this.SiteUrl == null)
                {
                    
                    //Special , these are webpart properties, user set
                    throw new InvalidWebpartValue("Invalid List name web part parameter (Configure web part)");
                }

                listSettings.templateStr = Resources.DefaultListTemplate; 
                
                listSettings.isOnQuickLaunch = true;
                listSettings.isAllowContentTypes = true;
                listSettings.isEnableFolderCreation = false;
                listSettings.isEnableVersioning = true;


                //Create it
                SPList createdList = listManager.CreateOrUpdateList(listSettings);
                return createdList;
            }

        }

        private void AddEntityToList(string listName, SPContentType entity)
        {

            using (ListManagementLib listManager = new ListManagementLib(SiteUrl))
            {
                //Get the list settings
                ListSettings listSettings = listManager.GetListSettings(listName); //Handy if it exists

                //It must exist? (Checked on start up)
                listSettings.contentTypesStr += entity.Name;
                listManager.CreateOrUpdateList(listSettings);

            }

        }


        public SPContentType CreateNewEntity(string listName , string entityName, string entityDescription)
        {
            using (ContentTypeManagmentLib ctManager = new ContentTypeManagmentLib(SiteUrl))//Ensure SPsite/web disposal
            {
                //Create it
                SPContentType newContentType =  ctManager.GetOrCreateContentType(Resources.DefaultEntityEditorContentTypeGroupName, entityName, Resources.DefaultContentTypeParentName, entityDescription);

                

                //assumption: we only permit one list , therefore this must be intended for the default list. So add it
                AddEntityToList(listName, newContentType);



                return newContentType;
            }
           

        }


        internal Dictionary<string, ContentTypeInfo> GetValidContentTypes()
        {
            Dictionary<string, ContentTypeInfo> entityNameAndID = new Dictionary<string, ContentTypeInfo>();
            using (ContentTypeManagmentLib ctManager = new ContentTypeManagmentLib(SiteUrl))//Ensure SPsite/web disposal
            using(ListManagementLib listManager = new ListManagementLib(SiteUrl))
            {

                List<SPContentType> ctList = ctManager.GetCTListByGroup(Resources.DefaultEntityEditorContentTypeGroupName);
                SPContentTypeCollection ctListValid = listManager.GetAllCTForList(this.ListName);

                //convert it to a str/id list for dropdowns
                 foreach (SPContentType curCtctListValid  in ctListValid)
                 {
                     //Ignore Document etc...
                     var x = from n in ctList where n.Name.Equals(curCtctListValid.Name) select n;
                     //var curCt = x.ToList()[0];
                     if (x.Count() > 0)
                     {
                         var curCt = x.ToList()[0];
                         Debug.WriteLine(String.Format("{0} {1}", curCt.Name, curCt.Id));
                         entityNameAndID[curCt.Id.ToString()] = new ContentTypeInfo(curCt);
                     }
                    
                 }

            }

            return entityNameAndID;

        }


        internal Dictionary<string, FieldInfo> GetEntityFields(string entityID)
        {
            Dictionary<string, FieldInfo> results = new Dictionary<string, FieldInfo>();
            using (ContentTypeManagmentLib ctManager = new ContentTypeManagmentLib(SiteUrl))//Ensure SPsite/web disposal
            {
                //IGNORE : Fields , use field refs 
                //http://msdn.microsoft.com/en-us/library/aa543680.aspx
               
                Dictionary<string, SPField> fields   =  ctManager.GetEntityFields(entityID);
               // foreach(SPField curField in fields){

               // //mode the data we need to a non SP object
               //     results.Add(new FieldInfo()
               //     {
               //         Name = curField.Title,
               //         Description = curField.Description,
               //         Type = curField.TypeAsString,
               //         Group = curField.Group.ToString()
               //     });
               // }

                //GetEntityFieldLinks
                List<SPFieldLink> fieldLinks = ctManager.GetEntityFieldLinks(entityID);
                foreach (SPFieldLink curFieldLink in fieldLinks)
                {
                   
                        SPField cField = fields[curFieldLink.Id.ToString()];
                        if (!cField.Group.Trim().Equals("_Hidden"))//Ignore hidden
                        {
                        //mode the data we need to a non SP object
                        results[cField.Id.ToString()] = new FieldInfo()
                        {
                            Name = curFieldLink.Name,
                            Description = cField.Description,
                            Type = cField.TypeAsString,
                            Group = cField.Group.ToString(),
                            Id = cField.Id.ToString()
                        };
                    }
                }

            }

            return results;
        }



        internal Dictionary<string, FieldInfo> GetAllFieldsOnSite()
        {
            Dictionary<string, FieldInfo> results = new Dictionary<string, FieldInfo>();
            //Load accepted Column group names
            List<string> acceptedGroupsStrList = Resources.AcceptedColumnGroups.Split(';').ToList<string>();
            acceptedGroupsStrList.Add(Resources.EntityExtensionColumnsNameStr);//Add the default new col group name 

            using (ContentTypeManagmentLib ctManager = new ContentTypeManagmentLib(SiteUrl))//Ensure SPsite/web disposal
            {
                List<SPField> fields = ctManager.GetAllFieldsOnSite();
                foreach (SPField curField in fields)
                {
                    if (acceptedGroupsStrList.Contains<string>(curField.Group.ToString()))
                    {
                        //mode the data we need to a non SP object
                        results[curField.Id.ToString()]= new FieldInfo()
                        {
                            Name = curField.Title,
                            Description = curField.Description,
                            Type = curField.TypeAsString,
                            Group = curField.Group.ToString(),
                            Id = curField.Id.ToString()
                        };
                    }
                    else
                    {

                        Debug.WriteLine(String.Format("[IGNORE COL] {0} : type : {1}", curField.Title, curField.Group.ToString()));
                    }
                }
            }
            return results;
            
        }

        internal void AddFieldToContentType(string contentName, string  fieldName)
        {

            using (ContentTypeManagmentLib ctManager = new ContentTypeManagmentLib(SiteUrl))//Ensure SPsite/web disposal
            {
                 
                ctManager.AddFieldToContentType(  contentName,   fieldName);

                 
            }

        }

        /// <summary>
        /// One group per list. Auto named.
        /// </summary>
        public TaxonomyCreateGroupResult CreateTaxonomyGroup(string listName)
        {
            using (TaxonomyManagementProxyLib taxLib = new TaxonomyManagementProxyLib(this.SiteUrl))
            {
               TaxonomyCreateGroupResult group =   taxLib.CreateMetadatGroup(listName + SharePointEntityProject.Properties.Resources.ListMetadataPostfixString, "Automatically generated metadata group, for list " + listName);
               return group;
            }
            
        }

        /// <summary>
        /// list all field types, for dropdown 
        /// </summary>
        public object GetAllValidFieldTypes()
        {
            using (FieldManagementLib fieldLib = new FieldManagementLib(SiteUrl))
            {
                fieldLib.GetAllFieldTypes();
            }
            return 1;
        }

        /// <summary>
        /// Creates a field, that  can be added to a CT. 
        /// Will create a metadata source if required. 
        /// </summary>
        public void CreateNewField(FieldInfo field)
        {
            
             
                //Create metadata if required.
               
                using (TaxonomyManagementProxyLib taxLib = new TaxonomyManagementProxyLib(this.SiteUrl))
                {
                    //Create input object
                    TaxonomyCreateTermSetArgs inputArgs = new TaxonomyCreateTermSetArgs()
                    {
                        TaxSetName = field.MetadataSetName,
                        Description = field.MetadataSetDescription,
                        GroupId = String.Format("{0}{1}", this.ListName, SharePointEntityProject.Properties.Resources.ListMetadataPostfixString),
                        IsOpenForTermCreation = Convert.ToBoolean(SharePointEntityProject.Properties.Resources.IsOpenForTermCreationDefaultValue),
                         URL = this.SiteUrl,
                    };
                    TaxonomyCreateTermSetResult termSet = taxLib.CreateMetadatTermSet(inputArgs);
                    taxLib.CreateNewTaxonomyField(field, termSet);
               
                
            
            }

            
            
        }
    }
}
